package com.wl.designpattern.proxy;

import java.lang.reflect.Proxy;

/**
 * 代理模式
 * 为其他对象提供一种代理以控制这个对象的访问。
 *
 * Subject（抽象主题类）：接口或者抽象类，声明真实主题与代理的共同接口方法。
 * RealSubject（真实主题类）：也叫做被代理类或被委托类，定义了代理所表示的真实对象，负责具体业务逻辑的执行，客户端可以通过代理类间接的调用真实主题类的方法。
 * Proxy（代理类）：也叫委托类，持有对真实主题类的引用，在其所实现的接口方法中调用真实主题类中相应的接口方法执行。
 * Client（客户端类）：使用代理模式的地方。
 *
 * 静态代理缺点
 * 静态代理如果接口新增一个方法，除了所有实现类（真实主题类）需要实现这个方法外，所有代理类也需要实现此方法。增加了代码维护的复杂度。
 * 代理对象只服务于一种类型的对象，如果要服务多类型的对象。必须要为每一种对象都进行代理，静态代理在程序规模稍大时就无法胜任了。
 *
 * 动态代理优点
 * 可以通过一个代理类完成全部的代理功能，接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理（InvocationHandler.invoke）。当接口方法数量较多时，我们可以进行灵活处理，而不需要像静态代理那样每一个方法进行中转。
 * 动态代理的应用使我们的类职责更加单一，复用性更强。
 *
 * 动态代理缺点
 * 不能对类进行代理，只能对接口进行代理，如果我们的类没有实现任何接口，那么就不能使用这种方式进行动态代理（因为$Proxy()这个类集成了Proxy,Java的集成不允许出现多个父类）。
 *
 * 应用场景
 * 当一个对象不能或者不想直接访问另一个对象时，可以通过一个代理对象来间接访问。为保证客户端使用的透明性，委托对象和代理对象要实现同样的接口。
 *
 * 被访问的对象不想暴露全部内容时，可以通过代理去掉不想被访问的内容。
 *
 * android中应用
 * ActivityManagerProxy
 *
 * Created by wangliang on 2021/2/27.
 */
public class Test {
    public static void main(String[] args) {
        People domestic = new Domestic();        //创建国内购买人
        People oversea = new Oversea(domestic);  //创建海外代购类并将domestic作为构造函数传递
        oversea.buy();
    }

    private static void dynamicProxy() {
        People domestic = new Domestic();                                 //创建国内购买人
        DynamicProxy proxy = new DynamicProxy(domestic);                  //创建动态代理
        ClassLoader classLoader = domestic.getClass().getClassLoader();   //获取ClassLoader
        People oversea = (People) Proxy.newProxyInstance(classLoader, new Class[]{People.class}, proxy); //通过 Proxy 创建海外代购实例 ，实际上通过反射来实现的。
        oversea.buy(); //调用海外代购的buy()
    }
}
